package cn.yr.clock.aop;

/**
 * @title LogRecordAspect
 * @description 切面 打印请求、返回参数信息
 * @author Lang 1102076808@qq.com
 * @date 2020/7/11 0:25
 */

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.NotFoundException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * 仿JFinal请求日志打印
 *
 * @author Lang 1102076808@qq.com
 * @date 2020/7/20 22:59
 */
@Aspect
@Component
@Slf4j
public class LogRecordAspect {

    private static final ThreadLocal<SimpleDateFormat> sdf = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    protected static boolean locateMethodLineNumber = true;
    private static ClassPool pool = ClassPool.getDefault();

    @Value("${spring.profiles.active}")
    private String active;

    @Pointcut("execution(* cn.yr..*.controller.*Controller.*(..))")
    public void executionService() {
    }

    @Around("executionService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        /*if (!"dev".equals(active)) {
            return pjp.proceed();
        }*/
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(sra)) {
            log.error("请求异常");
            return null;
        }
        HttpServletRequest request = sra.getRequest();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String paraString = JSONUtil.toJsonStr(request.getParameterMap());
        Integer line = getLineNumber(pjp.getSignature().getName(), pjp.getTarget().getClass().getName());
        StringBuffer buffer = new StringBuffer("\n南风怡人 request report ---------")
                .append((sdf.get()).format(new Date())).append(" --------------------------\n");
        buffer.append("Url         : ").append(method).append("  ").append(uri).append("\n");
        buffer.append("Controller  : ").append(pjp.getSignature().getDeclaringTypeName())
                .append(".(").append(pjp.getTarget().getClass().getSimpleName()).append(".java:").append(line).append(")\n");
        buffer.append("Method      : ").append(pjp.getSignature().getName()).append("\n");
        buffer.append("UrlPara     : ").append(paraString).append("\n");
        buffer.append("--------------------------------------------------------------------------------\n");
        System.out.println(buffer);
        // result的值就是被拦截方法的返回值
        Object result = pjp.proceed();
        String sbResponse = "\n返回值: " +
                pjp.getTarget().getClass().getSimpleName() + " --- " +
                pjp.getSignature().getName() + ": " +
                JSONUtil.toJsonStr(result) + "\n";
        System.out.println(sbResponse);
        return result;
    }

    private int getLineNumber(String methodName, String className) {
        int lineNumber = 1;
        if (locateMethodLineNumber) {
            try {
                lineNumber = pool.get(className).getDeclaredMethod(methodName).getMethodInfo().getLineNumber(0);
            } catch (NotFoundException e) {
            }
        }
        return lineNumber;
    }
}
